import datetime
import time
import cv2
import requests
import ctypes

player = ctypes.windll.kernel32

allow_upload = False

positionA = (160, 10, 300, 60)
positionB = (460, 460, 461, 461)
positionC = (465, 465, 466, 466)
frame_buffer_a = None
frame_buffer_b = None
frame_buffer_c = None
upload_a = False
upload_b = False
upload_c = False
move_num_a = 0
move_num_b = 0
move_num_c = 0

buffer = datetime.datetime.now()
record_buffer = buffer
FPS = 0
FPSBuffer = 0
lastTime = round(time.time())

camera = cv2.VideoCapture(0)
time.sleep(0.25)

alarm = False


def update(stu_id):
    payload = {'stuId': stu_id}
    r = requests.get('http://ali.lifanko.cn/idp/miao/update.php', params=payload)
    print(datetime.datetime.now().strftime("%B %d %I:%M:%S%p") + ' - update: ' + stu_id + ' status code: ' + str(
        r.status_code))


while True:
    thisTime = round(time.time())
    if thisTime != lastTime:
        lastTime = thisTime
        FPS = FPSBuffer
        FPSBuffer = 0
    else:
        FPSBuffer += 1

    (grabbed, frame) = camera.read()
    if not grabbed:
        break

    # 调整该帧转换为灰阶图像并且对其进行高斯模糊
    gray = cv2.GaussianBlur(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), (21, 21), 3)

    # 裁剪图像
    frameA = gray[positionA[1]:positionA[3], positionA[0]:positionA[2]]
    frameB = gray[positionB[1]:positionB[3], positionB[0]:positionB[2]]
    frameC = gray[positionC[1]:positionC[3], positionC[0]:positionC[2]]

    text = ''

    ##########################################################################################
    if frame_buffer_a is None:
        frame_buffer_a = frameA
    else:
        # 计算当前帧和第一帧的不同
        frame_delta = cv2.absdiff(frameA, frame_buffer_a)
        thresh = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1]
        # 扩展阀值图像填充孔洞，然后找到阀值图像上的轮廓
        thresh = cv2.dilate(thresh, None, iterations=2)
        (_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 遍历轮廓
        for c in cnts:
            # 计算轮廓的边界框，在当前帧中画出该框
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.circle(frame, (int(x + w / 2) + positionA[0], int(y + h / 2) + positionA[1]), int(min(w, h) / 2),
                       (255, 0, 0), -1)
        if cnts:
            text += 'A-Y'
            if not alarm:
                player.Beep(1000, 500)
                alarm = True
        else:
            text += 'A-N'
            alarm = False
    ##########################################################################################
    if frame_buffer_b is None:
        frame_buffer_b = frameB
    else:
        # 计算当前帧和第一帧的不同
        frame_delta = cv2.absdiff(frameB, frame_buffer_b)
        thresh = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1]
        # 扩展阀值图像填充孔洞，然后找到阀值图像上的轮廓
        thresh = cv2.dilate(thresh, None, iterations=2)
        (_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 遍历轮廓
        for c in cnts:
            # 计算轮廓的边界框，在当前帧中画出该框
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.circle(frame, (int(x + w / 2) + positionB[0], int(y + h / 2) + positionB[1]), int(min(w, h) / 2),
                       (0, 255, 0), -1)
        if cnts:
            text += 'B-Y'
        else:
            text += 'B-N'
    ##########################################################################################
    if frame_buffer_c is None:
        frame_buffer_c = frameC
    else:
        # 计算当前帧和第一帧的不同
        frame_delta = cv2.absdiff(frameC, frame_buffer_c)
        thresh = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1]
        # 扩展阀值图像填充孔洞，然后找到阀值图像上的轮廓
        thresh = cv2.dilate(thresh, None, iterations=2)
        (_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 遍历轮廓
        for c in cnts:
            # 计算轮廓的边界框，在当前帧中画出该框
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.circle(frame, (int(x + w / 2) + positionC[0], int(y + h / 2) + positionC[1]), int(min(w, h) / 2),
                       (0, 0, 255), -1)
        if cnts:
            text += 'C-Y'
        else:
            text += 'C-N'
    ##########################################################################################
    if int(datetime.datetime.now().strftime('%y%m%d%H%M%S')) - int(buffer.strftime('%y%m%d%H%M%S')) >= 5:
        buffer = datetime.datetime.now()
        if text[0:3] == 'A-Y':
            frame_buffer_a = None
            upload_a = True
            move_num_a += 1
        if text[3:6] == 'B-Y':
            frame_buffer_b = None
            upload_b = True
            move_num_b += 1
        if text[6:9] == 'C-Y':
            frame_buffer_c = None
            upload_c = True
            move_num_c += 1

    # 上传信息
    if int(datetime.datetime.now().strftime('%y%m%d%H%M%S')) - int(record_buffer.strftime('%y%m%d%H%M%S')) >= 60:
        record_buffer = datetime.datetime.now()
        if allow_upload:
            if upload_a and move_num_a > 5:
                update('311622000915')
            else:
                print('noUpload-A')
            if upload_b and move_num_b > 5:
                update('311608070813')
            else:
                print('noUpload-B')
            if upload_c and move_num_c > 5:
                update('311708010627')
            else:
                print('noUpload-C')
        upload_a = False
        upload_b = False
        upload_c = False
        move_num_a = 0
        move_num_b = 0
        move_num_c = 0

    # 在当前帧写上文字以及时间戳
    cv2.putText(frame, "Status: {}".format(text), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
    cv2.putText(frame,
                datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p") + ' FPS: ' + str(
                    FPS) + ' Move Num: A-' + str(
                    move_num_a) + ' B-' + str(move_num_b) + ' C-' + str(move_num_c), (10, frame.shape[0] - 10),
                cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)

    cv2.rectangle(frame, positionA[0:2], positionA[2:4], (255, 0, 0))
    cv2.rectangle(frame, positionB[0:2], positionB[2:4], (0, 255, 0))
    cv2.rectangle(frame, positionC[0:2], positionC[2:4], (0, 0, 255))

    # 显示当前帧
    cv2.imshow("Security Feed", frame)

    # 如果空格键被按下，结束程序
    key = cv2.waitKey(1) & 0xFF
    if key == ord(" "):
        break

# 清理摄像机资源并关闭打开的窗口
camera.release()
cv2.destroyAllWindows()
